package com.sevilla28.modelado;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Environment;
import android.os.Vibrator;
import android.widget.Toast;

import com.sevilla28.app.R;
import com.sevilla28.app.XMLParser;

public class Cantoral {
	
	private Map<String, Cancion> cantoral = new HashMap<String, Cancion>();
	private Context context;
	private Activity activity;
	private MediaPlayer mp = new MediaPlayer();
	private static final String NOMBRE_CANTORAL = "cantoral.pdf";
	
	/**
	 * Constructor
	 * @param con
	 * @param activity
	 */
	public Cantoral(Context con, Activity activity) {
		this.context = con;
		this.activity = activity;
		XMLParser xml = new XMLParser();
		try {
			this.cantoral = xml.parse(con.getResources());
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Obtiene una cancion aleatoria del cantoral a partir de un tipo de cancion 
	 * @param tipo
	 * @return El nombre de la cancion
	 */
	public String getCancionTipoAleatoria(String tipocancion)  {
		List<Cancion> listaCanciones = new ArrayList<Cancion>();
		Set<String> set = cantoral.keySet();
		Iterator<String> it = set.iterator();
		while(it.hasNext())  {
			String idCancion = (String)it.next();
			if(cantoral.get(idCancion).getTipos().contains(TipoCancion.valueOf(tipocancion)))
			listaCanciones.add(cantoral.get(idCancion));
		}
		Random r = new Random();
		return listaCanciones.get(r.nextInt(listaCanciones.size())).getNombre();
	}
	
	/**
	 * Obtiene el ID de una cancion a raiz de su nombre
	 * @param name
	 * @return ID de la cancion
	 */
	public String getIDFromNombre(String nombre) {
		String IDCancion = "";
		Set<String> set = cantoral.keySet();
		Iterator<String> it = set.iterator();
		while(it.hasNext())  {
			String idCancion = (String)it.next();
			Cancion cancion = cantoral.get(idCancion);
			if(cancion.getNombre().equals(nombre))
				return idCancion;
		}
		return IDCancion;
	}
	
	/**
	 * Obtiene el nombre de una cancion a partir de su ID
	 * @param id
	 * @return Nombre de la cancion
	 */
	public String getNameFromID(String id) {
		return cantoral.get(id).getNombre();
	}
	
	/**
	 * Reproduce una cancion a partir de su ID
	 * @param id
	 */
	public void playMusicFromID(String songID) {
		try{
			mp.reset();
			AssetFileDescriptor descriptor;
			descriptor = context.getAssets().openFd(cantoral.get(songID).getRutaCancion());
			mp.setDataSource( descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength() );
			descriptor.close();
			mp.prepare();
			mp.start();
			alert("Reproduciendo '" + getNameFromID(songID) + "'");
		} catch(Exception e) { e.printStackTrace(); }
	}
	
	/**
	 * Obtiene el numero de canciones del cantoral
	 * @return
	 */
	public int getCantoralLength() {
		return cantoral.size();
	}
	
	/**
	 * Indica si una cancion tiene fichero de audio reproducible
	 * @param id
	 * @return
	 */
	public boolean hasSong(String id) {
		return !(cantoral.get(id).getRutaCancion().equals(" ") || cantoral.get(id).getRutaCancion().equals(""));
	}
	
	/**
	 * Indica si una cancion tiene video asociado en youtube 
	 * @param id
	 * @return
	 */
	public boolean hasVideo(String id) {
		return !(cantoral.get(id).getYoutubeID().equals(" ") || cantoral.get(id).getYoutubeID().equals(""));
	}
	
	/**
	 * Obtiene el ID del video de youtube de una cancion a partir de su id
	 * @param id
	 * @return id de youtube
	 */
	public String getYoutubeID(String songID) {
		return cantoral.get(songID).getYoutubeID();
	}
	
	/**
	 * Detiene o reanuda la reproduccion de canciones
	 */
	public void pauseResume() {
		if(mp.isPlaying()) {
			mp.pause();
			alert("Pause");
		} else {
			mp.start();
			alert("Play");
		}
	}
	
	/**
	 * Detiene la reproduccion de canciones
	 */
	public void stopMusic() {
		if(mp.isPlaying()) {
		mp.stop();
		alert("Stop");
		}
	}
	
	/**
	 * Reproduce una cancion aleatoria.
	 */
	public void shuffleSong() {
		List<String> cancionesConMusica = new ArrayList<String>();
		Random r = new Random();
		Set<String> canciones = cantoral.keySet();
		Iterator<String> it = canciones.iterator();
		while(it.hasNext()) {
			String idCancion = (String) it.next();
			if(!(cantoral.get(idCancion).getRutaCancion().equals(" ") || cantoral.get(idCancion).getRutaCancion().equals(""))) {
				cancionesConMusica.add(idCancion);
			}
		}
		playMusicFromID(cancionesConMusica.get(r.nextInt(cancionesConMusica.size())));
	}
	
	/**
	 * Lanza un cuadro de alerta con el texto pasado como parametro
	 * @param texto
	 */
	public void alert(String texto) {
		CharSequence text = texto;
		int duration = Toast.LENGTH_SHORT;
		Toast toast = Toast.makeText(this.context, text, duration);
		toast.show();
	}
	
	/**
	 * Lanza la aplicacion lectora de PDF para abrir el cantoral
	 */
	public void openCantoral() {
		//Comprobamos si existe ya el cantoral en la memoria
		if(!new File(context.getExternalFilesDir(null), NOMBRE_CANTORAL).exists()) {
			File file = null;
			try {
				//Abrimos el pdf
				InputStream is = context.getResources().openRawResource(R.raw.cantoral);
				//Creamos un fichero en la tarjeta de memoria que se llame cantoral
				if (hasStorage(true)) {
					file = new File(context.getExternalFilesDir(null), NOMBRE_CANTORAL);
				} else {
					//Sin SD no podemos leer PDF
					alert("Necesitas una memoria SD para leer el fichero PDF. Comprueba que no la tengas conectada al PC.");
					return;
				}
				//Copiamos el fichero en la tarjeta
				OutputStream os = new FileOutputStream(file);
				byte[] buf = new byte[1024];
				int len;
				while ((len = is.read(buf)) > 0) {
					os.write(buf, 0, len);
				}
				is.close();
				os.close();
			} catch (IOException e1) {
				alert("Ha ocurrido un error");
			}
		}
		//Lanzamos la actividad que abrira el pdf con algun lector
		try{
			File file = new File(context.getExternalFilesDir(null), NOMBRE_CANTORAL);
	        Uri path = Uri.fromFile(file);
	        Intent intent = new Intent(Intent.ACTION_VIEW);
	        intent.setDataAndType(path, "application/pdf");
	        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
	        activity.startActivity(intent);
		} catch (ActivityNotFoundException e) {
            alert("Necesitas tener instalado un lector de PDF. Prueba con el Adobe reader en Google Play");
        } catch(Exception e) {
        	alert("Error");
        }
	}
	
	/**
	 * Indica si disponemos de tarjeta SD donde guardar el fichero PDF
	 * @param requireWriteAccess
	 * @return
	 */
	public static boolean hasStorage(boolean requireWriteAccess) {  
	    String state = Environment.getExternalStorageState();
	    if (Environment.MEDIA_MOUNTED.equals(state)) {  
	        return true;  
	    } else if (!requireWriteAccess  
	            && Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {  
	        return true;  
	    }  
	    return false;  
	}
	
	public void vibrar(int tiempo) {
		// Get instance of Vibrator from current Context
		Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
		 
		// Vibrate for 300 milliseconds
		v.vibrate(tiempo);

	}
}
